package mission2.model;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.*;
public class toList {

    @SuppressWarnings("unchecked")
    public static void main (String[] args) throws IOException
    {
        ArrayList<Elements> t = StringToList("(5+3)");
        Iterator<Elements> it = t.iterator();
        
        while(it.hasNext()) {
        	Elements  element = it.next();
        	System.out.println(element.toString() + " de " + element.getClass());
        }
    }
    /*
     * @pre: s doit �tre une variable du type String representant une expression analytique valable.
     *       Le programme s'exŽcute correctement m�me si une fonction inconnue est inscrite dans s.
     *       si s contient: "nimporte(x)" le tableau renvoyŽ sera donnŽ par
     *       t[1]="nimporte"
     *       t[2]="("
     *       t[3]="x"
     *       t[4]=")"
     *       
     * @post: renvoie un tableau dont chaque entree est un bloc
     *        un bloc est soit une fonction soit un operande soit une parenth�se ou un nombre
     */
    public static ArrayList<Elements> StringToList (String s) throws IOException
    {
    	ArrayList<String> t = new ArrayList<String>();
    	
        //String[] t=new String[s.length()+1];
        StringReader reader = new StringReader(s);
        int end = reader.read();//pour arreter la lecture
        String temp = Character.toString((char)end);
        //int k = 1;//indice du tableau
        
        while(end!=-1)
        {
            if (isANumber(temp))//Si temp est un nombre
            {
                end=reader.read();
                String temp2=Character.toString((char)end);
                if (isANumber(temp2))//charact�re suivant est un nombre
                { 
                    temp+=temp2;
                    
                }
                else//charact�re suivant n'est pas un nombre
                {
                    t.add(temp);
                    temp=temp2;
                    //k++;
                }
            }
            else
            {
                if(isAnOperand(temp))
                {// Si l'un de ces symboles: directement rajouter dans le tableau
                    
                    t.add(temp);
                    end=reader.read();
                    temp=Character.toString((char)end);
                   // k++;
                }
                else
                { //en cas d'une fonction ex: sin, cos,... ou tout autre sŽquence inconnue
                    end=reader.read();
                    
                    String temp2=Character.toString((char)end);
                    if (isANumber(temp2)||isAnOperand(temp2))
                    {
                        t.add(temp);
                        //k++;
                        temp=temp2;
                    }
                    else
                    {
                        temp+=temp2;
                    }    
                }
            }
        }
        return stringToObject(t);    
    }
    public static boolean isANumber(String s)
    {//Renvoie true si s represente un nombre
        try{
            int a= Integer.parseInt(s);
            return true;
        }
        catch (NumberFormatException e)
        {
            return false;
        }
    }
    public static boolean isAnOperand(String s)
    {//renvoie true si s est un operande ou une parenthese
        return s.equals("(") ||s.equals(")") ||s.equals("^") ||s.equals("x")||s.equals("-")||s.equals("+")||s.equals("*")||s.equals("/");
    }
    
    private static ArrayList<Elements> stringToObject(ArrayList<String> listString) {
    	ArrayList<Elements> al = new ArrayList<Elements>();
    	Iterator<String> it = listString.iterator();

    	// Cree les objets en fonction de la chaine de caractere
    	while(it.hasNext()) {
    		String element = it.next();
    		
    		if(element.equals("+")) {
    			al.add(new OpPlus());
    		}
    		else if(element.equals("-")) {
    			al.add(new OpMinus());
    		}
    		else if(element.equals("^")) {
    			al.add(new OpPower());
    		}
    		else if(element.equals("/")) {
    			al.add(new OpDivide());
    		}
    		else if(element.equals("*")){
    			al.add(new OpMult());
    		}
    		else if(element.equals("cos")){
    			al.add(new FunCos());
    		}
    		else if(element.equals("sin")){
    			al.add(new FunSin());
    		}
    		else if(isValidInt(element)) {
    			al.add(new Numbers(Integer.valueOf(element)));
    		}
    		else {
    			al.add(new Variable(element));
    		}
    	}
    	
    	// Retourne la liste d'object
    	return al;
    }
    
    private static boolean isValidInt(String toTest) {
		Pattern p = Pattern.compile("(\\d)+");
		Matcher m = p.matcher(toTest);
		if (m.lookingAt() && m.start() == 0 && m.end() == (toTest.length()))
			return true;
		return false;
	}
}